<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class ExportPermission extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'export:permission {param}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '导出 permission 日志 和 TXT';

    /**
     * Create a new command instance.
     *
     * @return void
     */


    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $param = $this->argument('param');
        $fullRouteUri = app()->routes->getRoutes();
        $routes = self::getRouteUriContent($fullRouteUri, $param);
        self::diffPermissionJsContent($routes,$param);
        $this->info('日志:database/permission/permission.log  SQL:database/permission/permission.txt');
    }

    /**
     * FunctionName：getRouteUriContent
     * Description：001 获取路由里的数据
     * Author：lwl
     * @param $routes
     * @param string $param
     * @return array
     */
    protected static function getRouteUriContent($routes, string $param)
    {
        $appName = config('app.name');
        foreach ($routes as $key => $value) {
            $uri = $value->uri;
            $method = $value->methods[0];
            if (strpos($uri, $appName . "/{$param}") !== false) {
                $namePrefix = $value->action['name_prefix'];
                $diffNamePrefix = explode('@', $namePrefix);
                $route = end($diffNamePrefix) . '/' . $diffNamePrefix[0] . '/' . $value->action['as'];
                $data[$key] = '/' . str_replace("/$param", '', $route) . '@@' . $method;
            }
        }
        return array_values($data);
    }

    /**
     * FunctionName：diffPermissionJsContent
     * Description：002 对比 Permission.js 内容 然后写入
     * Author：lwl
     * @param array $routeUri
     * @param string $param
     */
    protected static function diffPermissionJsContent(array $routeUri,string $param)
    {
        $hasContent = file_get_contents(database_path('permission/permission.js'));
        //是否执行过 命令 是
        if (!empty($hasContent)) {
            $oldRouteUri = explode(PHP_EOL, $hasContent);
            $newRouteUri = array_diff($routeUri, $oldRouteUri);
            $content = empty($newRouteUri) ? [] : $newRouteUri;
        } else { //否
            $content = $routeUri;
        }
        if (!empty($content)) {
            self::putPermissionLog($content,$param);
            self::putPermissionJsContent($content);
            self::putPermissionTxtContent($param,$content);
        }
    }

    /**
     * FunctionName：putPermissionLog
     * Description：003 写入log
     * Author：lwl
     * @param array $content
     * @param string $param
     */
    protected static function putPermissionLog(array $content,string $param)
    {
        $dataTime = date('Y-m-d H:i:s');
        $permissionLogContent = '';
        $appName = config('app.name');
        foreach ($content as  $value){
            $value =  trim($value,'/');
            $valueArray = explode('@@', $value);
            $method = end($valueArray);
            $minValue  = str_replace($appName.'/',$appName.'.',$value);
            $routePrefix = str_replace($appName.'/','',$valueArray[0]);
            $routePrefixArray = str_replace('.','\/',$routePrefix);
            $routeJson = "{'url':'\/$appName\/$param\/$routePrefixArray','method':$method}}";
            $permissionLogContent .= '[' . $dataTime . '] CREATE: ' . $minValue . ' > {"name":"' . $minValue . '","type":"api","scopes":["__' . $appName . '","' . $param . '"],"content":' . $routeJson . '}' . PHP_EOL;
        }
        $permissionLogHandle = fopen(database_path('permission/permission.log'), 'a');
        fputs($permissionLogHandle, $permissionLogContent);
        fclose($permissionLogHandle);
    }

    /**
     * FunctionName：putPermissionJsContent
     * Description：004 写入permission.js
     * Author：lwl
     * @param array $permissionJsContents
     */
    protected static function putPermissionJsContent(array $permissionJsContents)
    {
        $permissionJsHandle = fopen(database_path('permission/permission.js'), 'a');
        $permissionJsContent = '';
        foreach ($permissionJsContents as $value) {
            $permissionJsContent .= $value . PHP_EOL;
        }
        fputs($permissionJsHandle, $permissionJsContent);
        fclose($permissionJsHandle);
    }

    /**
     * FunctionName：putPermissionTxtContent
     * Description：005 写入 permission.txt
     * Author：lwl
     * @param string $param
     * @param array $content
     */
    protected static function putPermissionTxtContent(string $param,array $content)
    {

        $appName = config('app.name');
        $nowDate = date('Y-m-d H:i:s');
        $permissionSqlContent = '';
        foreach (array_values($content) as $key => $item) {
            if (!empty($item)) {
                $routeNameArray = explode('@@', $item);
                $name = $routeNameArray[0];
                $newName = str_replace( '/', '.', trim($name,'/'));
                $routePrefix = str_replace($appName . '.', '', $newName);
                $method = end($routeNameArray);
                $url = "\\\/{$appName}\\\/$param\\\/" . str_replace('.', '\\\/', $routePrefix);
                $permissionSqlContent .= <<<EOF
                INSERT INTO `staff`.`permissions`(`name`, `type`, `scopes`, `content`, `translations`, `created_at`, `updated_at`) VALUES ('{$newName}', 'api', '[\"__{$appName}\",\"staff\"]', '{\"url\":"{$url}",\"method\":\"{$method}\"}', NULL, '{$nowDate}', '{$nowDate}');\r
EOF;
            }
        }
        $permissionSqlHandle = fopen(database_path('permission/permission.txt'), 'a');
        fputs($permissionSqlHandle, trim($permissionSqlContent));
        fclose($permissionSqlHandle);
    }


    /**
     * 伪代码
     * 01  获取所有的路由数据 从其中 挑选 staff 下的 路由地址 通过 项目名称+命令参数(staff)+路由中别名匹配，生成特定路由结构 (唯一值)
     * 02  获取 permission.js 中内容 与  01 步骤 特定路由结构 比对出差集
     * 03  将 02 步骤的 差集数据 写入 permission.log
     * 04  将 02 步骤的 差集数据 再次 生成特定路由结构 (唯一值) 写入 permission.js
     * 05  将 02 步骤的 差集数据 写入 permission.txt
     * 06  根据 permission.log 的时间找到对应的日志 将对应日志里 与 permission.text 对比 找到 对应的 SQL
     */
}
